﻿package net.wangit.dev.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.wangit.MapList;
import net.wangit.Row;
import net.wangit.context.ActionContext;
import net.wangit.dev.LabelRule;
import net.wangit.jdbc.DB;
import net.wangit.util.Checker;
import net.wangit.view.tree.Tree;


public abstract class ObjectTree {

	public static final String GROUP_ICON = "/domain/dev/c/group.png";
	public static final String CATALOG_CHECK_VALUE = "-";
	private static final String SQL_GROUP = "select gid,n from CGROUP where t=? order by o,gid";
	private String groupPrefix;
	private String groupType;
	private Map<String, List<Row>> groupedRows;
	private boolean showNullGroup;
	protected boolean hasItem;
	protected boolean check;
	protected int objectCount;

	public ObjectTree() {
		groupedRows = new HashMap<String, List<Row>>();
		hasItem = true;
		check = false;
	}

	public int[] addTree(ActionContext ac, DB db, Tree root) throws Exception {
		groupType = getComponentType();
		groupPrefix = (new StringBuilder(String.valueOf(check ? "_g" : "_G")))
				.append(
						groupType.length() != 1 ? groupType
								: (new StringBuilder("0")).append(groupType)
										.toString()).toString();
		showNullGroup = showNullGroup();
		MapList groups = db.query(ObjectTree.SQL_GROUP, groupType, 12);
		MapList objects = getObjects(db);
		group(groups, objects);
		int itemCount = 0;
		if (!Checker.isEmpty(groups)) {
			for (int i = 0; i < groups.size(); i++)
				itemCount += addGroup(ac, db, root, groups.getRow(i));

		}
		itemCount += addObjects(ac, db, root, groupedRows.get(null));
		return (new int[] { objectCount, itemCount });
	}

	public int getItemsCount(DB db) throws Exception {
		String tableName = getItemsTableName();
		if (tableName == null) {
			return -1;
		} else {
			String sql = (new StringBuilder("select count(*) rowcount from "))
					.append(tableName).toString();
			MapList list = db.query(sql);
			return list.getRow(0).getInt("rowcount", 0);
		}
	}

	private void group(MapList groups, MapList objects) {
		if (!Checker.isEmpty(groups)) {
			for (int i = 0; i < groups.size(); i++) {
				String groupId = groups.getRow(i).get("gid");
				groupedRows.put(groupId, new ArrayList<Row>());
			}

		}
		groupedRows.put(null, new ArrayList<Row>());
		if (!Checker.isEmpty(objects)) {
			for (int i = 0; i < objects.size(); i++) {
				Row row = objects.getRow(i);
				String groupId = row.get("gid");
				List<Row> rows = groupedRows.get(groupId);
				if (rows == null)
					rows = groupedRows.get(null);
				rows.add(row);
			}

		}
	}

	private int addGroup(ActionContext ac, DB db, Tree root, Row row)
			throws Exception {
		String groupId = row.get("gid");
		List<Row> rows = groupedRows.get(groupId);
		if (Checker.isEmpty(rows) && !showNullGroup)
			return 0;
		Tree group = new Tree();
		group.setId((new StringBuilder(String.valueOf(groupPrefix))).append(
				groupId).toString());
		group.setIcon(ObjectTree.GROUP_ICON);
		String name = row.get("n");
		int itemCount = addObjects(ac, db, group, rows);
		if (check) {
			group.setCheckValue(ObjectTree.CATALOG_CHECK_VALUE);
			setGroup(group, groupId, name);
		} else {
			String label = LabelRule.getLabel(ac, ObjectTreeHelper
					.getLableRule(ac), groupId, name);
			name = getGroupName(label, group.size() - 1, itemCount);
			group.setName(name);
			group.setAttribute(getGroupAttribute());
			group.setAction((new StringBuilder("/dev/group.do?m=e&grouptype="))
					.append(groupType).append("&groupid=").append(groupId)
					.toString());
		}
		if (!check || !Checker.isEmpty(group.getLeafs()))
			root.add(group);
		return itemCount;
	}

	private int addObjects(ActionContext ac, DB db, Tree group, List<Row> rows)
			throws Exception {
		int itemCount = 0;
		for (int i = 0; i < rows.size(); i++)
			itemCount += addObject(ac, db, group, (Row) rows.get(i));

		return itemCount;
	}

	private String getGroupName(String label, int objectCount, int itemCount) {
		StringBuffer name = new StringBuffer(label);
		name.append(" ").append(objectCount);
		if (hasItem && itemCount >= 0)
			name.append("/").append(itemCount);
		return name.toString();
	}

	protected abstract String getItemsTableName();

	protected abstract String getComponentType();

	protected abstract MapList getObjects(DB db) throws Exception;

	protected abstract int addObject(ActionContext actioncontext, DB db,
			Tree tree, Row row) throws Exception;

	protected abstract boolean showNullGroup();

	protected abstract String getGroupAttribute();

	public void setCheck(boolean check) {
		this.check = check;
	}

	protected void setGroup(Tree group, String groupId, String name) {
		group.setName((new StringBuilder(String.valueOf(groupId))).append(" ")
				.append(name).append(" ").append(group.size() - 1).toString());
	}
}
